package com.xinziruo.crawl.application.crawl.impl;

import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.xinziruo.crawl.application.crawl.CrawlApiObjectScheduleService;
import com.xinziruo.crawl.domain.crawl.CrawlApiObject;
import com.xinziruo.crawl.domain.crawl.CrawlApiObjectRepository;
import com.xinziruo.crawl.infrastruture.util.ExceptionUtils;

/**
 * 
 * @author loudyn
 * 
 */
@Transactional
public class QuartzCrawlApiObjectScheduleService implements CrawlApiObjectScheduleService {

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.youboy.crawl.application.crawl.CrawlApiObjectScheduleService#
	 * registerCrawlJob(com.youboy.crawl.domain.crawl.CrawlApiObject)
	 */
	@Override
	public void registerCrawlJob(CrawlApiObject crawlApiObject) {
		try {

			crawlApiObjectRepository.store(crawlApiObject.verifyParseExpressions().verifyParams());
			JobDetail job = new JobDetail();
			job.setName(crawlApiObject.getId());
			job.setJobClass(QuartzCrawlJob.class);
			job.setGroup(QuartzCrawlJob.SCHEDULE_GROUP);

			if (isAlreadyExistJobDetail(job)) {
				removeJobDetail(job);
			}

			// save the grouponCrawlRule to job dataMap
			job.getJobDataMap().put(QuartzCrawlJob.CRAWL_API_OBJECT, crawlApiObject);
			quartzScheduler.addJob(job, true);
			Trigger trigger = new CronTrigger(
												job.getName(),
												QuartzCrawlJob.SCHEDULE_GROUP,
												job.getName(),
												job.getGroup(),
												crawlApiObject.getCronExpression()
											);
			quartzScheduler.scheduleJob(trigger);
		} catch (Exception e) {
			e.printStackTrace();
			throw ExceptionUtils.toUnchecked(e);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.youboy.crawl.application.crawl.CrawlApiObjectScheduleService#
	 * removeCrawlJob(com.youboy.crawl.domain.crawl.CrawlApiObject)
	 */
	@Override
	public void removeCrawlJob(CrawlApiObject crawlApiObject) {
		try {
			JobDetail job = new JobDetail();
			job.setName(crawlApiObject.getId());
			job.setJobClass(QuartzCrawlJob.class);
			job.setGroup(QuartzCrawlJob.SCHEDULE_GROUP);

			removeJobDetail(job);
			crawlApiObjectRepository.delete(crawlApiObject);
		} catch (SchedulerException e) {
			throw ExceptionUtils.toUnchecked(e);
		}
	}

	private void removeJobDetail(JobDetail jobDetail) throws SchedulerException {
		quartzScheduler.pauseJob(jobDetail.getName(), jobDetail.getGroup());
		quartzScheduler.unscheduleJob(jobDetail.getName(), jobDetail.getGroup());
		quartzScheduler.deleteJob(jobDetail.getName(), jobDetail.getGroup());
	}

	private boolean isAlreadyExistJobDetail(JobDetail jobDetail) throws SchedulerException {
		return null != quartzScheduler.getJobDetail(jobDetail.getName(), jobDetail.getGroup());
	}

	private Scheduler quartzScheduler;
	private CrawlApiObjectRepository crawlApiObjectRepository;

	@Autowired
	public void setQuartzScheduler(Scheduler quartzScheduler) {
		this.quartzScheduler = quartzScheduler;
	}

	@Autowired
	public void setCrawlApiObjectRepository(CrawlApiObjectRepository crawlApiObjectRepository) {
		this.crawlApiObjectRepository = crawlApiObjectRepository;
	}

}
